x86 vmx: Unrestricted guest (realmode) support
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 28 May 2009 08:51:43 +0000 (09:51 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 28 May 2009 08:51:43 +0000 (09:51 +0100)
It allows fully virtualized guests to run real mode and unpaged mode
code natively in the VMX mode when EPT is turned on. With the
unrestricted guest there is no need to emulate the guest real mode
code in the vm86 container or in the emulator. Also the guest big real
mode code works like native.

This patch enhances Xen to use the unrestricted guest feature if
available on the processor. It also adds a new xen parameter to
disable the unrestricted guest feature at the boot time.

Signed-off-by: Nitin A Kamble <nitin.a.kamble@intel.com>
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/vmx/vmcs.h

index 400d31de74ea64ab266a19b98f3b514fa208c8a5..881a9a832b74b4e9f014f3b976e3fb1acbad7724 100644 (file)
@@ -41,6 +41,9 @@
 static int opt_vpid_enabled = 1;
 boolean_param("vpid", opt_vpid_enabled);
 
+static int opt_unrestricted_guest_enabled = 1;
+boolean_param("unrestricted_guest", opt_unrestricted_guest_enabled);
+
 /* Dynamic (run-time adjusted) execution control flags. */
 u32 vmx_pin_based_exec_control __read_mostly;
 u32 vmx_cpu_based_exec_control __read_mostly;
@@ -68,6 +71,7 @@ static void __init vmx_display_features(void)
     P(cpu_has_vmx_vpid, "Virtual-Processor Identifiers (VPID)");
     P(cpu_has_vmx_vnmi, "Virtual NMI");
     P(cpu_has_vmx_msr_bitmap, "MSR direct-access bitmap");
+    P(cpu_has_vmx_unrestricted_guest, "Unrestricted Guest");
 #undef P
 
     if ( !printed )
@@ -139,6 +143,9 @@ static void vmx_init_vmcs_config(void)
                SECONDARY_EXEC_ENABLE_EPT);
         if ( opt_vpid_enabled )
             opt |= SECONDARY_EXEC_ENABLE_VPID;
+        if ( opt_unrestricted_guest_enabled )
+            opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST;
+
         _vmx_secondary_exec_control = adjust_vmx_controls(
             min, opt, MSR_IA32_VMX_PROCBASED_CTLS2);
     }
@@ -156,7 +163,9 @@ static void vmx_init_vmcs_config(void)
         if ( must_be_one & (CPU_BASED_INVLPG_EXITING |
                             CPU_BASED_CR3_LOAD_EXITING |
                             CPU_BASED_CR3_STORE_EXITING) )
-            _vmx_secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+            _vmx_secondary_exec_control &=
+                ~(SECONDARY_EXEC_ENABLE_EPT |
+                  SECONDARY_EXEC_UNRESTRICTED_GUEST);
     }
 
 #if defined(__i386__)
@@ -532,7 +541,9 @@ static int construct_vmcs(struct vcpu *v)
     }
     else
     {
-        v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_EPT;
+        v->arch.hvm_vmx.secondary_exec_control &= 
+            ~(SECONDARY_EXEC_ENABLE_EPT | 
+              SECONDARY_EXEC_UNRESTRICTED_GUEST);
         vmx_vmexit_control &= ~(VM_EXIT_SAVE_GUEST_PAT |
                                 VM_EXIT_LOAD_HOST_PAT);
         vmx_vmentry_control &= ~VM_ENTRY_LOAD_GUEST_PAT;
index dddd9ec108e2a60d757eacdefa7312dc95dbc662..e256f51de6c59ec20cd0dcd0d7e49775ec142bb4 100644 (file)
@@ -1062,8 +1062,10 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
     {
     case 0: {
         int realmode;
-        unsigned long hw_cr0_mask =
-            X86_CR0_NE | X86_CR0_PG | X86_CR0_PE;
+        unsigned long hw_cr0_mask = X86_CR0_NE;
+
+        if ( !vmx_unrestricted_guest(v) )
+            hw_cr0_mask |= X86_CR0_PG | X86_CR0_PE;
 
         if ( paging_mode_shadow(v->domain) )
            hw_cr0_mask |= X86_CR0_WP;
@@ -1091,7 +1093,9 @@ static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr)
         }
 
         realmode = !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE); 
-        if ( realmode != v->arch.hvm_vmx.vmx_realmode )
+
+        if ( (!vmx_unrestricted_guest(v)) &&
+             (realmode != v->arch.hvm_vmx.vmx_realmode) )
         {
             enum x86_segment s; 
             struct segment_register reg[x86_seg_tr + 1];
@@ -1431,15 +1435,10 @@ void start_vmx(void)
     }
 
     if ( cpu_has_vmx_ept )
-    {
-        printk("VMX: EPT is available.\n");
         vmx_function_table.hap_supported = 1;
-    }
 
     if ( cpu_has_vmx_vpid )
     {
-        printk("VMX: VPID is available.\n");
-
         vpid_bitmap = xmalloc_array(
             unsigned long, BITS_TO_LONGS(VPID_BITMAP_SIZE));
         BUG_ON(vpid_bitmap == NULL);
index 80640e0d5a0575d268acfeb3e021eff768f28486..c2b468e66467af1b03dfd6b5a59ab898de0e80d5 100644 (file)
@@ -170,6 +170,7 @@ extern u32 vmx_vmentry_control;
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING           0x00000040
+#define SECONDARY_EXEC_UNRESTRICTED_GUEST       0x00000080
 extern u32 vmx_secondary_exec_control;
 
 extern bool_t cpu_has_vmx_ins_outs_instr_info;
@@ -194,6 +195,11 @@ extern bool_t cpu_has_vmx_ins_outs_instr_info;
     (vmx_cpu_based_exec_control & CPU_BASED_MONITOR_TRAP_FLAG)
 #define cpu_has_vmx_pat \
     (vmx_vmentry_control & VM_ENTRY_LOAD_GUEST_PAT)
+#define cpu_has_vmx_unrestricted_guest \
+    (vmx_secondary_exec_control & SECONDARY_EXEC_UNRESTRICTED_GUEST)
+#define vmx_unrestricted_guest(v)               \
+    ((v)->arch.hvm_vmx.secondary_exec_control & \
+     SECONDARY_EXEC_UNRESTRICTED_GUEST)
 
 /* GUEST_INTERRUPTIBILITY_INFO flags. */
 #define VMX_INTR_SHADOW_STI             0x00000001